各リージョンに存在する SNS トピックの一覧と SNS サブスクリプションの詳細を一括で取得したい
コンバンハ、千葉(幸)です。
今回のシチュエーションは以下です。
- 複数のリージョンに SNS トピックおよび SNS サブスクリプションが存在する
- いくつかの SNS サブスクリプションがアンサブスクライブされている可能性がある
- SNS サブスクリプションが認証なしで無効化できる状態であるか確認したい
全量を確認しつつ、SNS トピックと SNS サブスクリプションの突き合わせ、現状の設定確認をしたいです。
ひとまず各リージョンにおいて「SNS トピックの一覧」と「SNS サブスクリプションの詳細」を AWS CLI で一括で取ることにしました。
各リージョンで SNSトピックの一覧を取得する
ひとまずベースとなる SNS トピックの一覧を取得します。
シンプルに以下を実行しました。
for region in $(aws ec2 describe-regions --query 'Regions[].[RegionName]' --output text); do echo "### Listing SNS topics for region $region" aws sns list-topics --query 'Topics[]' --output text --region $region done
出力イメージは以下です。
### Listing SNS topics for region ap-south-1 arn:aws:sns:ap-south-1:000000000000:GuardDutyTopic arn:aws:sns:ap-south-1:000000000000:notify-mumbai ### Listing SNS topics for region eu-north-1 ### Listing SNS topics for region eu-west-3 arn:aws:sns:eu-west-3:000000000000:GuardDutyTopic ### Listing SNS topics for region eu-west-2 arn:aws:sns:eu-west-2:000000000000:GuardDutyTopic ### Listing SNS topics for region eu-west-1 arn:aws:sns:eu-west-1:000000000000:GuardDutyTopic ### Listing SNS topics for region ap-northeast-3 ……
aws ec2 describe-regions
で有効なリージョンの一覧を取得し、各リージョンに対してループで処理を実行します。
今回のケースに限らず、複数リージョンを対象に実行したい処理で使い回しができる形かと思います。
余談ですが、--all-regions
オプションを付与することで有効でない(オプトインが済んでいない)リージョンも取得できます。
% aws ec2 describe-regions --all-regions --output table --------------------------------------------------------------------------------- | DescribeRegions | +-------------------------------------------------------------------------------+ || Regions || |+-----------------------------------+-----------------------+-----------------+| || Endpoint | OptInStatus | RegionName || |+-----------------------------------+-----------------------+-----------------+| || ec2.ap-south-2.amazonaws.com | not-opted-in | ap-south-2 || || ec2.ap-south-1.amazonaws.com | opt-in-not-required | ap-south-1 || || ec2.eu-south-1.amazonaws.com | not-opted-in | eu-south-1 || || ec2.eu-south-2.amazonaws.com | not-opted-in | eu-south-2 || || ec2.me-central-1.amazonaws.com | not-opted-in | me-central-1 || || ec2.ca-central-1.amazonaws.com | opt-in-not-required | ca-central-1 || || ec2.eu-central-1.amazonaws.com | opt-in-not-required | eu-central-1 || || ec2.eu-central-2.amazonaws.com | not-opted-in | eu-central-2 || || ec2.us-west-1.amazonaws.com | opt-in-not-required | us-west-1 || || ec2.us-west-2.amazonaws.com | opt-in-not-required | us-west-2 || || ec2.af-south-1.amazonaws.com | not-opted-in | af-south-1 || || ec2.eu-north-1.amazonaws.com | opt-in-not-required | eu-north-1 || || ec2.eu-west-3.amazonaws.com | opt-in-not-required | eu-west-3 || || ec2.eu-west-2.amazonaws.com | opt-in-not-required | eu-west-2 || || ec2.eu-west-1.amazonaws.com | opt-in-not-required | eu-west-1 || || ec2.ap-northeast-3.amazonaws.com | opt-in-not-required | ap-northeast-3 || || ec2.ap-northeast-2.amazonaws.com | opt-in-not-required | ap-northeast-2 || || ec2.me-south-1.amazonaws.com | not-opted-in | me-south-1 || || ec2.ap-northeast-1.amazonaws.com | opt-in-not-required | ap-northeast-1 || || ec2.sa-east-1.amazonaws.com | opt-in-not-required | sa-east-1 || || ec2.ap-east-1.amazonaws.com | not-opted-in | ap-east-1 || || ec2.ap-southeast-1.amazonaws.com | opt-in-not-required | ap-southeast-1 || || ec2.ap-southeast-2.amazonaws.com | opt-in-not-required | ap-southeast-2 || || ec2.ap-southeast-3.amazonaws.com | not-opted-in | ap-southeast-3 || || ec2.ap-southeast-4.amazonaws.com | not-opted-in | ap-southeast-4 || || ec2.us-east-1.amazonaws.com | opt-in-not-required | us-east-1 || || ec2.us-east-2.amazonaws.com | opt-in-not-required | us-east-2 || |+-----------------------------------+-----------------------+-----------------+|
各リージョンでaws sns list-topics
を実行します。このコマンドは SNS トピックが取得できるだけのシンプルなものです。
各リージョンの SNS サブスクリプションの詳細を一括で取得する
続いて各リージョンの SNS サブスクリプションの情報を取得していきます。
aws sns list-subscriptions
で必要な情報が取得できれば先ほどと同じようなコマンドで実現できるのですが、残念ながらそうはいきません。
取得できる情報例は以下で、ここには今回取得したいConfirmationWasAuthenticated
が含まれていません。
{ "Subscriptions": [ { "Owner": "123456789012", "Endpoint": "my-email@example.com", "Protocol": "email", "TopicArn": "arn:aws:sns:us-west-2:123456789012:my-topic", "SubscriptionArn": "arn:aws:sns:us-west-2:123456789012:my-topic:8a21d249-4329-4871-acc6-7be709c6ea7f" } ] }
ConfirmationWasAuthenticated
とは SNS サブスクリプションの確認(初回登録)が認証有りで行われたかどうかを表す属性であり、これがfalse
の場合、IAM 認証なしでサブスクリプション解除できてしまう状態です。
以下エントリのように「いつの間にかサブスクリプションが削除されていた」という事態になりかねません。
ConfirmationWasAuthenticated
属性を確認するにはaws sns get-subscription-attributes
コマンドの使用が必要です。
そのため、コマンドは以下の流れで実行します。
aws ec2 describe-regions
でリージョン一覧を取得- リージョンごとに以下を実行
aws sns list-subscriptions
で SNS サブスクリプション一覧を取得- SNS サブスクリプションごとに
aws sns get-subscription-attributes
で情報を取得
実際に組み立てたコマンド例は以下です。
for region in $(aws ec2 describe-regions --query 'Regions[].[RegionName]' --output text); do echo "### Listing SNS subscriptions for region $region" for subscription in $(aws sns list-subscriptions --region $region | jq -r '.Subscriptions | sort_by(.SubscriptionArn) | .[].SubscriptionArn') do aws sns get-subscription-attributes\ --subscription-arn $subscription --region $region\ | jq -r '.Attributes | [.SubscriptionArn,.ConfirmationWasAuthenticated,.Protocol,.Endpoint] | @tsv' done done
コマンドの実行結果例は以下の通り。
### Listing SNS subscriptions for region ap-south-1 arn:aws:sns:ap-south-1:000000000000:notify-mumbai:6e6ce52f-a64e-473d-b28d-e3b5d7f650c7 false email example@example.com ### Listing SNS subscriptions for region eu-north-1 ### Listing SNS subscriptions for region eu-west-3 ### Listing SNS subscriptions for region eu-west-2 ### Listing SNS subscriptions for region eu-west-1 ### Listing SNS subscriptions for region ap-northeast-3 arn:aws:sns:ap-northeast-3:000000000000:notify-osaka:9ee0bad1-b7ec-42f5-8113-2cb48044b9fa false email example@example.com ### Listing SNS subscriptions for region ap-northeast-2 arn:aws:sns:ap-northeast-2:000000000000:notify-seoul:7faad0d8-b2ac-4cff-b8b1-7dc1351f9791 false email example@example.com ### Listing SNS subscriptions for region ap-northeast-1 arn:aws:sns:ap-northeast-1:000000000000:Publish-to-Lambda:8851927b-d074-4a48-84e2-f01f2a6f6e7d false email example@example.com arn:aws:sns:ap-northeast-1:000000000000:Publish-to-Lambda:b54a1670-6021-4da7-9a58-86ba7ff436e1 true lambda arn:aws:lambda:ap-northeast-1:000000000000:function:sns-message-python arn:aws:sns:ap-northeast-1:000000000000:aes-siem-alert:65d05c6e-d851-4cad-a49d-23ea6952be4b false email example@example.com arn:aws:sns:ap-northeast-1:000000000000:insightwatch-InvokeLambdaFunctionTopic:0b62ba3a-9c1d-40e7-a9ac-9ad96e9f6054 true lambda arn:aws:lambda:ap-northeast-1:000000000000:function:insightwatch-create-message arn:aws:sns:ap-northeast-1:000000000000:insightwatch-NotificationTopic:c236965a-8957-4301-a67c-a1100cda2c8b false email example@example.com arn:aws:sns:ap-northeast-1:000000000000:notify-mail:4aab0fa9-7e22-4fe6-aea6-f99564ea4698 false email example@example.com arn:aws:sns:ap-northeast-1:000000000000:tedttopic:195d7b21-33ef-47e8-abf3-4aac8a0c55bf false email example@example.com ### Listing SNS subscriptions for region ca-central-1 ……以下略
1行ごとに以下情報がタブ区切りで出力されます。
- SNS サブスクリプションの ARN
ConfirmationWasAuthenticated
の値- プロトコル
- エンドポイント
あとはスプレッドシートなどで頑張ろう
ここまでで各リージョンの SNS トピックと SNS サブスクリプションの一覧が取得できました。
愚直にそれぞれの結果をスプレッドシートに貼り付けた例が以下です。(条件付き書式でリージョン部分は灰色に編みかけしている)
あとは両者を照らし合わせながら、
- あるべき SNS サブスクリプションが紐づいていない SNS トピックがないか
- 紐づく SNS トピックがない SNS サブスクリプションがないか *1
- 既存の SNS サブスクリプションの
ConfirmationWasAuthenticated
属性がどうなっているか
などなど、お好みの形でこねくりまわしましょう。
終わりに
各リージョンにおいて、SNS トピック一覧と SNS サブスクリプションの詳細一覧を取得したい、という話でした。
少しニッチなケースだったかもしれませんが、実際に試す際にコマンドを組み立てるのに30分くらい要したのでブログにまとめてみました。
aws ec2 describe-regions
で取得したリージョン一覧ごとにループ処理を実行する方法- ループ処理の中でさらにループ処理を実行する方法
が今回学べたので、そこそこ使い回しできるのではないかと思います。
なんらか参考になれば幸いです。
以上、 チバユキ (@batchicchi) がお送りしました。
参考
脚注
- てっきり SNS トピックを消したらそこに紐づく SNS サブスクリプションが併せて削除されると思っていたのですが、そうではないのですね…… ↩